package com.fansin.hyperledger.fabric.java.config;

import com.fansin.hyperledger.fabric.java.store.SampleUser;
import lombok.Data;
import org.hyperledger.fabric.sdk.Channel;
import org.hyperledger.fabric.sdk.ChannelConfiguration;
import org.hyperledger.fabric.sdk.User;
import org.hyperledger.fabric.sdk.helper.Config;
import org.hyperledger.fabric_ca.sdk.HFCAClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.io.File;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>Title: FabricConfiguration</p>
 * <p>Description: </p>
 *
 * @author zhaofeng
 * @version 1.0
 * @date 18-8-23
 */
//@Configuration
//@PropertySources({
//        @PropertySource(value = "classpath:application.yaml",ignoreResourceNotFound = true),
//}
//)
@Configuration
@ConfigurationProperties(prefix = "organization-config")
@Data
@Order(1)
public class FabricConfiguration {

    private String fabricHome;

    private Config config = Config.getConfig();

    private Map<String, Organization> organizations;

    private Boolean runningTLS = false;
    private Map<String, Properties> clientTLSProperties;
    private String certificateFile;
    private String clientCert;
    private String clientKey;


    private EnrollEnvironment enrollEnvironment;


    public Properties getEventHubProperties(String name,String orgName) {

        return getEndPointProperties("peer", name,orgName); //uses same as named peer

    }

    public Properties getPeerProperties(String name,String orgName) {

        return getEndPointProperties("peer", name,orgName);

    }

    public Properties getOrdererProperties(String name) {

        return getEndPointProperties("orderer", name,null);

    }

    public Properties getEndPointProperties(final String type, final String name,String orgName) {
        System.out.println("加载 crypto-config/ 下证书文件");

        Properties ret = new Properties();

        final String domainName = getDomainName(name);

        File cert = Paths.get(getCertificateFile()).toFile();
        if (!cert.exists()) {
            throw new RuntimeException(String.format("Missing cert file for: %s. Could not find at location: %s", name,
                    cert.getAbsolutePath()));
        }

        File clientCert;
        File clientKey;
        if ("orderer".equals(type)) {
            clientCert = Paths.get(getClientCert()).toFile();

            clientKey = Paths.get(getClientKey()).toFile();
        } else {
            clientCert = Paths.get(getOrganizations().get(orgName).getClientCert()).toFile();
            clientKey = Paths.get(getOrganizations().get(orgName).getClientKey()).toFile();
        }

        if (!clientCert.exists()) {
            throw new RuntimeException(String.format("Missing  client cert file for: %s. Could not find at location: %s", name,
                    clientCert.getAbsolutePath()));
        }

        if (!clientKey.exists()) {
            throw new RuntimeException(String.format("Missing  client key file for: %s. Could not find at location: %s", name,
                    clientKey.getAbsolutePath()));
        }
        ret.setProperty("clientCertFile", clientCert.getAbsolutePath());
        ret.setProperty("clientKeyFile", clientKey.getAbsolutePath());

        ret.setProperty("pemFile", cert.getAbsolutePath());

        ret.setProperty("hostnameOverride", name);
        ret.setProperty("sslProvider", "openSSL");
        ret.setProperty("negotiationType", "TLS");

        return ret;
    }

    private String getDomainName(final String name) {
        int dot = name.indexOf(".");
        if (-1 == dot) {
            return null;
        } else {
            return name.substring(dot + 1);
        }

    }

    @Data
    public static class Organization {

        private String name;
        private String mspid;
        private Map<String, String> peerLocations;
        private Map<String, String> ordererLocations;
        private Map<String, String> eventHubLocations;
        private String caLocation;
        private String domainName;
        private String caName;
        private Map<String, SampleUser> userMap = new ConcurrentHashMap<>();
        private HFCAClient caClient;
        private Properties caProperties;

        private SampleUser admin;
        private SampleUser peerAdmin;


        private String privateKeyDir;
        private String certificateFile;
        private String clientCert;
        private String clientKey;

        private ChannelConfig  channelConfig;

        public void addUser(SampleUser user) {
            userMap.put(user.getName(), user);
        }

        public User getUser(String name) {
            return userMap.get(name);
        }

    }

    @Data
    public static class ChannelConfig{

        private String name;
        private String channelConfigFile;
    }


    @Data
    public static class EnrollEnvironment {
        private String host = "localhost";
        private String profile = "tls";
        private String user = "admin";
        private String secret = "adminpw";
    }

}
